package com.gsbelarus.gedemin.salary.adapter;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.support.v7.widget.RecyclerView;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.gsbelarus.gedemin.lib.Utils;
import com.gsbelarus.gedemin.salary.R;
import com.gsbelarus.gedemin.salary.database.RealmHelper;
import com.gsbelarus.gedemin.salary.entity.StatisticPayslip;
import com.gsbelarus.gedemin.salary.util.CurrencyHelper;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class StatisticCardsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context context;
    private List<StatisticPayslip> list;
    private LineData chartData;
    private CurrencyHelper currencyHelper;
    private RealmHelper realmHelper;
    private Double startSum;

    private int headerCount = 0;

    private OnItemClickListener onItemClickListener;
    private OnHeaderClickListener onHeaderClickListener;

    private int posDifColor;
    private int negDifColor;
    private int zeroDifColor;

    public enum ItemTypes {
        HEADER, CARD_ITEM
    }

    public StatisticCardsAdapter(Context context, RealmHelper realmHelper) {
        this.context = context;
        this.realmHelper = realmHelper;
        list = new ArrayList<>();
        currencyHelper = CurrencyHelper.getInstance(context);

        com.github.mikephil.charting.utils.Utils.init(context.getResources());

        posDifColor = context.getResources().getColor(R.color.debit_color);
        negDifColor = context.getResources().getColor(R.color.red);
        zeroDifColor = Color.GRAY;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        switch (ItemTypes.values()[viewType]) {
            case HEADER:
                viewHolder = new HeaderVH(LayoutInflater.from(parent.getContext()).inflate(R.layout.statistic_cards_header, parent, false));
                break;
            case CARD_ITEM:
                viewHolder = new CardItemVH(LayoutInflater.from(parent.getContext()).inflate(R.layout.statistic_cards_item, parent, false));
                break;
        }
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (ItemTypes.values()[getItemViewType(position)]) {
            case HEADER:
                HeaderVH headerHolder = (HeaderVH) holder;

                headerHolder.chart.setData(chartData);
                headerHolder.chart.getLegend().setEnabled(false);
                headerHolder.chart.animateY(300);
                headerHolder.chart.invalidate();
                break;
            case CARD_ITEM:
                StatisticPayslip cardRow = list.get(position - headerCount);
                Calendar date = cardRow.getDate();
                CardItemVH cardHolder = ((CardItemVH) holder);

                cardHolder.date.setText(Utils.getMonthName(context, date.get(Calendar.MONTH)) + " " +
                        String.valueOf(date.get(Calendar.YEAR)));

                if (currencyHelper.getLastChoice() == CurrencyHelper.Kind.BYR) {
                    Spannable sum = new SpannableString(
                            currencyHelper.getConvertedSumString(realmHelper, date, cardRow.getTotalSum()));

                    if (Math.abs(cardRow.getTotalSum()) >= 1000)
                        sum.setSpan(new RelativeSizeSpan(0.7f), sum.length() - 3, sum.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

                    cardHolder.totalSum.setText(sum);
                } else
                    cardHolder.totalSum.setText(
                            currencyHelper.getConvertedSumString(realmHelper, date, cardRow.getTotalSum()) +
                                    currencyHelper.getKindOfCurrencyText(" "));

                if (cardRow.getDifference() > 0) {
                    cardHolder.difference.setTextColor(posDifColor);
                    cardHolder.differenceImage.setColorFilter(posDifColor, PorterDuff.Mode.SRC_ATOP);
                    cardHolder.differenceImage.setRotation(0);

                } else if (cardRow.getDifference() < 0) {
                    cardHolder.difference.setTextColor(negDifColor);
                    cardHolder.differenceImage.setColorFilter(negDifColor, PorterDuff.Mode.SRC_ATOP);
                    cardHolder.differenceImage.setRotation(90);

                } else {
                    cardHolder.difference.setTextColor(zeroDifColor);
                    cardHolder.differenceImage.setColorFilter(zeroDifColor, PorterDuff.Mode.SRC_ATOP);
                    cardHolder.differenceImage.setRotation(45);
                }

                if (currencyHelper.getLastChoice() == CurrencyHelper.Kind.BYR) {
                    Spannable sum = new SpannableString(currencyHelper.getFormatter().format(Math.abs(cardRow.getDifference())));

                    if (Math.abs(cardRow.getDifference()) >= 1000)
                        sum.setSpan(new RelativeSizeSpan(0.7f), sum.length() - 3, sum.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

                    cardHolder.difference.setText(sum);
                } else
                    cardHolder.difference.setText(currencyHelper.getFormatter().format(
                            Math.abs(cardRow.getDifference())) + currencyHelper.getKindOfCurrencyText(" "));
                break;
        }
    }

    @Override
    public int getItemCount() {
        return list.size() + headerCount;
    }

    @Override
    public int getItemViewType(int position) {
        return (headerCount != 0 && position == 0) ? ItemTypes.HEADER.ordinal() : ItemTypes.CARD_ITEM.ordinal();
    }

    private void createHeaderData() {
        if (list.isEmpty() && chartData != null)
            chartData.removeDataSet(0);
        ArrayList<Entry> yList = new ArrayList<>();
        ArrayList<String> xList = new ArrayList<>();
        int i = 0;
        for (StatisticPayslip item : list) {
            yList.add(new Entry((float) currencyHelper.getConvertedSum(realmHelper, item.getDate(), item.getTotalSum()), i));
            xList.add(new SimpleDateFormat("MM/yy").format(item.getDate().getTimeInMillis()));
            i++;
        }

        LineDataSet set = new LineDataSet(yList, "DataSet");
        set.setColor(ColorTemplate.getHoloBlue());
        set.setCircleColor(ColorTemplate.getHoloBlue());
        set.setLineWidth(5f);
        set.setCircleSize(5f);
        set.setFillAlpha(65);
        set.setFillColor(ColorTemplate.getHoloBlue());
        set.setDrawFilled(true);
        set.setDrawValues(false);

        ArrayList<LineDataSet> dataSets = new ArrayList<>();
        dataSets.add(set);

        chartData = new LineData(xList, dataSets);
    }

    private void createDifferenceSum() {
        if (list.size() > 1) {
            for (int i = 1; i < list.size(); i++) {
                StatisticPayslip previousItem = list.get(i - 1);
                StatisticPayslip currentItem = list.get(i);
                currentItem.setDifference(
                        currencyHelper.getConvertedSum(realmHelper, currentItem.getDate(), currentItem.getTotalSum()) -
                                currencyHelper.getConvertedSum(realmHelper, previousItem.getDate(), previousItem.getTotalSum())
                );
            }
        }
        if (!list.isEmpty() && startSum != null) {
            StatisticPayslip item = list.get(0);
            Calendar before = (Calendar) item.getDate().clone();
            before.add(Calendar.MONTH, -1);
            item.setDifference(currencyHelper.getConvertedSum(realmHelper, item.getDate(), item.getTotalSum()) -
                            currencyHelper.getConvertedSum(realmHelper, before, startSum)
            );
        }
    }

    public void setList(List<StatisticPayslip> list) {
        this.list = list;
        createDifferenceSum();
        createHeaderData();
        notifyDataSetChanged();
    }

    public void setStartSum(Double startSum) {
        this.startSum = startSum;
    }

    public void clear() {
        this.list.clear();
        createDifferenceSum();
        createHeaderData();
        notifyDataSetChanged();
    }

    public void showHeader(OnHeaderClickListener onHeaderClickListener) {
        this.headerCount = 1;
        this.onHeaderClickListener = onHeaderClickListener;
        notifyItemInserted(0);
    }

    public void hideHeader() {
        headerCount = 0;
        notifyItemRemoved(0);
    }

    public void notifyDataSetChangedList() {
        createDifferenceSum();
        createHeaderData();
        notifyItemRangeChanged(0, getItemCount());
    }

    public OnItemClickListener getOnItemClickListener() {
        return onItemClickListener;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public OnHeaderClickListener getOnHeaderClickListener() {
        return onHeaderClickListener;
    }

    public void setOnHeaderClickListener(OnHeaderClickListener onHeaderClickListener) {
        this.onHeaderClickListener = onHeaderClickListener;
    }

    class CardItemVH extends RecyclerView.ViewHolder implements View.OnClickListener {

        private TextView date;
        private TextView totalSum;
        private TextView difference;
        private ImageView differenceImage;

        CardItemVH(View itemView) {
            super(itemView);
            date = (TextView) itemView.findViewById(R.id.statistic_card_date);
            totalSum = (TextView) itemView.findViewById(R.id.statistic_card_total_sum);
            difference = (TextView) itemView.findViewById(R.id.statistic_card_difference_sum);
            differenceImage = (ImageView) itemView.findViewById(R.id.statistic_card_difference_image);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (onItemClickListener != null)
                onItemClickListener.onClick(list.get(getAdapterPosition() - headerCount), v, getAdapterPosition() - headerCount);
        }
    }

    public interface OnItemClickListener {
        void onClick(StatisticPayslip item, View view, int position);
    }

    class HeaderVH extends RecyclerView.ViewHolder implements View.OnClickListener {

        private LineChart chart;

        HeaderVH(View itemView) {
            super(itemView);
            chart = (LineChart) itemView.findViewById(R.id.chart);

            chart.setDrawGridBackground(false);
            chart.getXAxis().setDrawAxisLine(false);
            chart.getXAxis().setAvoidFirstLastClipping(true);
            chart.getAxisLeft().setStartAtZero(false);
            chart.getAxisLeft().setEnabled(false);
            chart.getAxisRight().setStartAtZero(false);
            chart.getAxisRight().setEnabled(false);
            chart.setDescription("");
            chart.setDoubleTapToZoomEnabled(false);
            chart.setTouchEnabled(false);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (onHeaderClickListener != null)
                onHeaderClickListener.onClick(v);
        }
    }

    public interface OnHeaderClickListener {
        void onClick(View view);
    }
}
